using DG.Tweening;
using hole.defaultgame;
using MEC;
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class Hole : MonoBehaviour
{
	[Serializable]
	public class EditorReferences
	{
		[Header("Group references")]
		public Transform[] sizeTransforms;

		public GameObject[] colliderGameObjects;

		public GameObject[] triggerGameObjects;

		[Header("Specific references")]
		public GameObject deathTimerObject;

		public Image deathTimerImage;

		public Text deathTimerText;

		[Space]
		public GameObject pseudoObject;

		public SpriteRenderer pseudoRankSprite;

		public Text pseudoText;

		[Space]
		public HoleTrigger fallingObjectTrigger;

		public HoleCore core;

		[Space]
		public Transform directionTransform;

		public SpriteRenderer directionTriangleSprite;

		[Space]
		public Transform skinTransform;

		[Space]
		public Image xpBarImage;

		[Space]
		public GameObject crownObject;

		[HideInInspector]
		public HoleCrown crown;

		public void Init()
		{
			crown = crownObject.GetComponent<HoleCrown>();
		}
	}

	public class UnityEventInt : UnityEvent<int>
	{
	}

	[SerializeField]
	public EditorReferences references = new EditorReferences();

	private bool _isLocalPlayer;

	private int _playerId;

	private string _pseudo = string.Empty;

	private int _points;

	private int _rank;

	private int _xp;

	private int _level = 1;

	private float _speed = 1f;

	private float _size = 1f;

	private bool _isDead;

	private bool _isBot;

	private SkinParameters _currentSkinParameters;

	private Skin _currentSkin;

	private Transform _cachedTransform;

	public UnityEventInt OnLevelChanged = new UnityEventInt();

	public bool IsLocalPlayer
	{
		get
		{
			return _isLocalPlayer;
		}
		set
		{
			_isLocalPlayer = value;
		}
	}

	public int PlayerId
	{
		get
		{
			return _playerId;
		}
		set
		{
			_playerId = value;
		}
	}

	public string Pseudo => _pseudo;

	public int Points
	{
		get
		{
			return _points;
		}
		set
		{
			_points = value;
		}
	}

	public int Rank => _rank;

	public int Xp => _xp;

	public int Level => _level;

	public float Speed => _speed;

	public float Size => _size;

	public bool IsDead => _isDead;

	public bool IsBot
	{
		get
		{
			return _isBot;
		}
		set
		{
			_isBot = value;
		}
	}

	public SkinParameters CurrentSkinParameters => _currentSkinParameters;

	public Vector3 ForwardDirection => references.directionTransform.forward;

	public Vector3 CurrentPosition => references.directionTransform.position;

	private void Awake()
	{
		references.Init();
		_cachedTransform = base.transform;
		references.pseudoText.resizeTextForBestFit = true;
	}

	private void Start()
	{
		references.deathTimerObject.SetActive(value: false);
		references.xpBarImage.fillAmount = 0f;
		_currentSkin.PlayFX();
	}

	public void SetHoleLayerIndex(int index)
	{
		GameObject[] colliderGameObjects = references.colliderGameObjects;
		foreach (GameObject gameObject in colliderGameObjects)
		{
			gameObject.layer = LayerMask.NameToLayer($"AlternateHole{index}");
		}
		GameObject[] triggerGameObjects = references.triggerGameObjects;
		foreach (GameObject gameObject2 in triggerGameObjects)
		{
			gameObject2.layer = LayerMask.NameToLayer($"Hole{index}");
		}
		references.fallingObjectTrigger.SetLayerOnEnter($"InHole{index}");
	}

	public void SetSkin(SkinParameters skin)
	{
		_currentSkinParameters = skin;
		_currentSkin = UnityEngine.Object.Instantiate(skin.skinPrefab, references.skinTransform);
		references.pseudoText.color = skin.shadowColor;
		references.directionTriangleSprite.transform.localPosition = new Vector3(0f, 0f, skin.triangleDirectionOffset);
		references.directionTriangleSprite.color = skin.triangleDirectionColor;
		references.xpBarImage.color = skin.xpCircleColor;
		references.xpBarImage.transform.localScale = Vector3.one * skin.xpCircleScale;
		references.xpBarImage.GetComponentInParent<Canvas>().sortingOrder = skin.xpCircleLayer;
	}

	public void AddXp(int xp, int requiredXp, int requiredXpNextLevel)
	{
		if (!_isDead)
		{
			_xp += xp;
			if(gameObject.name != "Player Local" && _level == 17)
				{
                references.xpBarImage.fillAmount = 1f;
			}
			else if (requiredXp == -1)
			{
				references.xpBarImage.fillAmount = 1f;
			}
			else if (_xp >= requiredXp && requiredXpNextLevel != -1)
			{
				SetLevel(_level + 1);
				_xp -= requiredXp;
				references.xpBarImage.fillAmount = Mathf.Clamp01((float)_xp / (float)requiredXpNextLevel);
			}
			else
			{
				references.xpBarImage.fillAmount = Mathf.Clamp01((float)_xp / (float)requiredXp);
			}
		}
	}

	public void AddPoints(int pts)
	{
		_points += pts;
	}

	public void SetLevel(int level)
	{
		if(gameObject.name == "Player Local")
		{
            _level = Mathf.Clamp(level, 0, 20);
		}
		else
		{
            _level = Mathf.Clamp(level, 0, 19);
        }
        float num = (float)(_level - 1) / 19f;
		SetSpeed(Mathf.Lerp(0.65f, 2.5f, num));
		SetSize(Mathf.Lerp(2f, 40f, num));
		references.fallingObjectTrigger.SetMinimumSize(_level);
		references.crown.SetSize(num);
		_currentSkin.SetSize(num);
		references.deathTimerObject.transform.localScale = new Vector3(Mathf.Lerp(2f, 40f, num), 1f, Mathf.Lerp(2f, 40f, num));
		OnLevelChanged.Invoke(_level);
	}

	public void SetSpeed(float speed)
	{
		_speed = speed;
	}

	public void SetSize(float size)
	{
		_size = size;
		Transform[] sizeTransforms = references.sizeTransforms;
		foreach (Transform transform in sizeTransforms)
		{
			transform.localScale = new Vector3(size, 1f, size);
		}
	}

	public void SetPseudo(string pseudo)
	{
		_pseudo = pseudo;
		references.pseudoText.text = pseudo;
	}

	public void SetRank(int rank)
	{
		RankManager.RankParameters rankParameters = RankManager.Instance.GetRankParameters(rank - 1);
		references.pseudoRankSprite.sprite = rankParameters.icon;
	}

	public void SetRotation(Quaternion rotation)
	{
		references.directionTransform.rotation = rotation;
		if ((bool)_currentSkinParameters && _currentSkinParameters.enableRotation)
		{
			references.skinTransform.rotation = rotation;
		}
	}

	public void SetPosition(Vector3 position)
	{
		_cachedTransform.position = position;
	}

	public void TranslatePosition(Vector3 translation)
	{
		_cachedTransform.position += translation;
	}

	public void ShowCrown(bool s)
	{
		if (references.crownObject.activeSelf != s)
		{
			references.crownObject.SetActive(s);
		}
	}

	public void Die(bool respawn)
	{
		references.pseudoObject.SetActive(value: false);
		references.core.gameObject.SetActive(value: false);
		Transform[] sizeTransforms = references.sizeTransforms;
		foreach (Transform target in sizeTransforms)
		{
			target.DOKill();
			target.DOScale(new Vector3(0f, 1f, 0f), 0.2f);
		}
		GameObject[] triggerGameObjects = references.triggerGameObjects;
		foreach (GameObject gameObject in triggerGameObjects)
		{
			gameObject.SetActive(value: false);
		}
		_currentSkin.StopFX();
		_isDead = true;
		if (respawn)
		{
			if (IsLocalPlayer)
			{
				UIManager.Instance.DeathComponent.Show();
				references.deathTimerObject.SetActive(value: true);
			}
			Timing.RunCoroutine(DeathCoroutine().CancelWith(base.gameObject), Segment.Update);
		}
	}

	private IEnumerator<float> DeathCoroutine()
	{
		float cooldown = 5f;
		while (cooldown > 0f)
		{
			cooldown -= Time.deltaTime;
			references.deathTimerImage.fillAmount = cooldown / 5f;
			references.deathTimerText.text = Mathf.FloorToInt(Mathf.Clamp(cooldown, 0f, 5f) + 1f).ToString();
			yield return 0f;
		}
		Respawn();
	}

	public void Respawn()
	{
		_isDead = false;
		_currentSkin.PlayFX();
		references.pseudoObject.SetActive(value: true);
		references.core.gameObject.SetActive(value: true);
		references.deathTimerObject.SetActive(value: false);
		GameObject[] triggerGameObjects = references.triggerGameObjects;
		foreach (GameObject gameObject in triggerGameObjects)
		{
			gameObject.SetActive(value: true);
		}
		if (IsLocalPlayer)
		{
			UIManager.Instance.DeathComponent.Hide();
		}
		SetLevel(_level);
		Transform[] sizeTransforms = references.sizeTransforms;
		foreach (Transform transform in sizeTransforms)
		{
			transform.localScale = new Vector3(0f, 1f, 0f);
			transform.DOScale(new Vector3(_size, 1f, _size), 0.2f).SetEase(Ease.OutBack);
		}
	}

	public bool IsValidTarget(int level)
	{
		return _level < level && !IsDead;
	}

	public Transform GetTargetTransform()
	{
		return _cachedTransform;
	}
}
